package cn.itsource.ymcc.service.impl;

import cn.itsource.openfeign.CourseFeignClient;
import cn.itsource.openfeign.EsCourseFeignClient;
import cn.itsource.ymcc.common.constant.OrderStatus;
import cn.itsource.ymcc.common.constant.RConst;
import cn.itsource.ymcc.common.constant.TaskConstants;
import cn.itsource.ymcc.common.result.JsonResult;
import cn.itsource.ymcc.common.util.AssertUtil;
import cn.itsource.ymcc.common.util.CodeGenerateUtils;
import cn.itsource.ymcc.domain.*;
import cn.itsource.ymcc.dto.KillPlaceOrderDto;
import cn.itsource.ymcc.dto.PlaceOrderDto;
import cn.itsource.ymcc.dto.PreOrderDto;
import cn.itsource.ymcc.mapper.CourseOrderMapper;
import cn.itsource.ymcc.producer.OrderProducer;
import cn.itsource.ymcc.service.ICourseOrderItemService;
import cn.itsource.ymcc.service.ICourseOrderService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zcj
 * @since 2023-12-08
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {
    @Autowired
    private EsCourseFeignClient esCourseFeignClient;
    @Autowired
    private ICourseOrderItemService courseOrderItemService;
    @Autowired
    private OrderProducer orderProducer;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private CourseFeignClient courseFeignClient;

    /**
     * 保存订单
     * @param orderDto
     * @return
     */
    @Override
    public JsonResult placeOrder(PlaceOrderDto orderDto,Long loginId) {
        //能防止一般用户
        Boolean b = redisTemplate.hasKey(orderDto.getCourseIds().get(0).toString());
        redisTemplate.delete(orderDto.getCourseIds().get(0).toString());
        AssertUtil.isTrue(b,"请勿重复提交");

        List<Long> courseIds = orderDto.getCourseIds();
        //去查询es?
        JsonResult courseDocByCourseIds = esCourseFeignClient.getCourseDocByCourseIds(courseIds);
        List<CourseDoc> courseDocList = JSONObject.parseArray(JSON.toJSONString(courseDocByCourseIds.getData()), CourseDoc.class);

        //去保存订单
        CourseOrder courseOrder = new CourseOrder();
        String orderNo = CodeGenerateUtils.generateOrderSn(loginId);
        courseOrder.setCreateTime(new Date());
        courseOrder.setOrderNo(orderNo);
        super.saveOrUpdate(courseOrder);
        //保存明细
        List<CourseOrderItem> list = saveCourseOrderItem(courseDocList, courseOrder);
        courseOrder.setUserId(loginId);
        courseOrder.setTitle("普通订单");
        courseOrder.setPayType(orderDto.getPayType());
        courseOrder.setOrderType(RConst.Num.INT_0);

        PayOrder payOrder = new PayOrder();
        payOrder.setOrderNo(orderNo);
        payOrder.setCreateTime(new Date());
        payOrder.setAmount(courseOrder.getPayAmount());
        payOrder.setPayType(orderDto.getPayType());

        List<String> collect = orderDto.getCourseIds().stream()
                .map(id -> id.toString()).collect(Collectors.toList());

        payOrder.setRelationId(String.join(",",collect));
        payOrder.setUserId(loginId);
        payOrder.setSubject(courseOrder.getTitle());
        payOrder.setPayStatus(OrderStatus.ORDER_SUCCESS);
        Map<String,Object> param = new HashMap<>();
        param.put("list",list);
        param.put("courseOrder",courseOrder);
        orderProducer.createPayOrderTransaction(param,payOrder);


        //发送MQ消息通知用户下单成功
        Map<String,Object> map = new HashMap<>();
        map.put("userId",loginId);
        map.put("content","该"+orderNo+"订单已下单成功，请尽快支付");
        orderProducer.notice(JSON.toJSONString(map));
        //返回订单号  前端拿订单号跳转支付页面
        return JsonResult.success().setData(orderNo);
    }

    @Override
    public JsonResult killPlaceOrder(KillPlaceOrderDto orderDto, Long loginId) {
        //能防止一般用户
        Boolean b = redisTemplate.hasKey(orderDto.getOrderNo());
        redisTemplate.delete(orderDto.getOrderNo());
        AssertUtil.isTrue(b,"请勿重复提交");
        //保存主表
        PreOrderDto preOrderDto = (PreOrderDto)redisTemplate.opsForValue().get(TaskConstants.KEY_PREFIX_PRE_ORDER + ":" + orderDto.getOrderNo());
        AssertUtil.isNotNull(preOrderDto,"购买时间已过期");
        Long courseId = preOrderDto.getCourseId();
        JsonResult jsonResult = courseFeignClient.get(courseId);
        CourseMarket course = JSON.parseObject(JSONObject.toJSONString(jsonResult.getData()), CourseMarket.class);
        CourseOrder courseOrder = new CourseOrder();
        BeanUtils.copyProperties(preOrderDto,courseOrder);
        courseOrder.setCreateTime(new Date());
        courseOrder.setTotalCount(preOrderDto.getCount());
        courseOrder.setTotalAmount(course.getPriceOld());
        courseOrder.setPayAmount(preOrderDto.getPrice());
        BigDecimal subtract = course.getPriceOld().subtract(preOrderDto.getPrice());
        courseOrder.setDiscountAmount(subtract);
        courseOrder.setStatusOrder(RConst.Num.INT_0);
        courseOrder.setPayType(orderDto.getPayType());
        courseOrder.setOrderType(RConst.Num.INT_1);
        super.saveOrUpdate(courseOrder);
        //保存订单明细
        CourseOrderItem courseOrderItem = new CourseOrderItem();
        courseOrderItem.setOrderId(courseOrder.getId());//？
        courseOrderItem.setOrderNo(courseOrder.getOrderNo());//
        courseOrderItem.setAmount(preOrderDto.getPrice());
        courseOrderItem.setPrice(preOrderDto.getPrice());
        courseOrderItem.setCount(RConst.Num.INT_1);
        courseOrderItem.setCourseId(preOrderDto.getCourseId());
        courseOrderItem.setCourseName(preOrderDto.getCourseName());
        courseOrderItem.setCoursePic(preOrderDto.getCoursePic());
        //构建支付单数据
        PayOrder payOrder = new PayOrder();
        payOrder.setOrderNo(orderDto.getOrderNo());
        payOrder.setCreateTime(new Date());
        payOrder.setAmount(courseOrder.getPayAmount());
        payOrder.setPayType(orderDto.getPayType());
        payOrder.setRelationId(preOrderDto.getCourseId().toString());
        payOrder.setUserId(loginId);
        payOrder.setSubject(courseOrder.getTitle());
        payOrder.setPayStatus(OrderStatus.ORDER_SUCCESS);
        //构建事务消息
        Map<String,Object> param = new HashMap<>();
        List<CourseOrderItem> list = new ArrayList<>();
        list.add(courseOrderItem);
        param.put("list",list);
        param.put("courseOrder",courseOrder);
        orderProducer.createPayOrderTransaction(param,payOrder);
        //发送MQ消息通知用户下单成功
        Map<String,Object> map = new HashMap<>();
        map.put("userId",loginId);
        map.put("content","该"+orderDto.getOrderNo()+"订单已下单成功，请尽快支付");
        orderProducer.notice(JSON.toJSONString(map));
        //返回订单号  前端拿订单号跳转支付页面
        return JsonResult.success().setData(orderDto.getOrderNo());
    }

    /**
     * 保存课程订单明细
     * @param courseDocList
     */
    private List<CourseOrderItem> saveCourseOrderItem(List<CourseDoc> courseDocList, CourseOrder courseOrder ) {
        //保存订单明细
        List<CourseOrderItem> list = new ArrayList<>();
        //支付金额
        Double payAmount = new Double(0);
        //总金额
        Double countAmount = new Double(0);
        for (CourseDoc courseDoc : courseDocList) {
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            courseOrderItem.setOrderId(courseOrder.getId());//？
            courseOrderItem.setOrderNo(courseOrder.getOrderNo());//
            courseOrderItem.setAmount(new BigDecimal(courseDoc.getPrice()));
            payAmount +=courseDoc.getPrice();
            courseOrderItem.setPrice(new BigDecimal(courseDoc.getPriceOld()));
            countAmount += courseDoc.getPriceOld();
            courseOrderItem.setCount(RConst.Num.INT_1);
            courseOrderItem.setCourseId(courseDoc.getId());
            courseOrderItem.setCourseName(courseDoc.getName());
            courseOrderItem.setCoursePic(courseDoc.getPic());
            list.add(courseOrderItem);
        }
        courseOrder.setTotalAmount(new BigDecimal(countAmount));
        courseOrder.setPayAmount(new BigDecimal(payAmount));
        courseOrder.setDiscountAmount(new BigDecimal(countAmount - payAmount));
        courseOrder.setTotalCount(courseDocList.size());
        courseOrder.setStatusOrder(OrderStatus.ORDER_SUCCESS);
        return list;
    }
}
